﻿using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using UnityEngine;
public class HttpConnection
{
    public Action completeEvent;
    public Action<HttpConnection> dataHandler;
    private string _url;
    private string _method;
    private string _content_type = ContentType.TEXT;
    private int _timeout;
    private CookieContainer _cookie;
    private StringBuilder _string_builder;
    private byte[] _request_data;
    private byte[] _response_data;

    public HttpConnection(string url, string method, int timeout = 600000)
    {
        _url = url;
        _method = method;
        _timeout = timeout;
    }

    public string contentType
    {
        set
        {
            _content_type = value;
        }
    }

    public CookieContainer Cookie
    {
        set
        {
            _cookie = value;
        }
    }

    public void AddParameter(string key, string value)
    {
        if (_string_builder == null)
            _string_builder = new StringBuilder();
        if (_string_builder.Length > 0)
            _string_builder.Append("&");
        _string_builder.Append(string.Format("{0}={1}", key, value.ToString()));
    }

    public void AddForm(WWWForm form)
    {
        _request_data = form.data;
    }

    public void AddJson(string str)
    {
        byte[] data = Encoding.UTF8.GetBytes(str);
        _request_data = data;
    }

    public void Send()
    {
        HttpWebRequest request = null;
        string finalUrl = _url;
        if (_string_builder != null)
        {
            if (!finalUrl.Contains("?"))
                finalUrl += "?";
            if (!finalUrl.EndsWith("?"))
                finalUrl += "&";
            finalUrl += _string_builder.ToString();
        }
        if (_url.StartsWith("https"))
        {
            ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) =>
            {
                return true;
            };
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Ssl3;
        }
        try
        {
            switch (_content_type)
            {
                case ContentType.TEXT:
                    request = WebRequest.CreateHttp(finalUrl);
                    request.Method = _method;
                    request.ContentType = _content_type;
                    request.Timeout = _timeout;
                    break;
                case ContentType.FORM:
                    {
                        request = WebRequest.CreateHttp(_url);
                        request.Method = _method;
                        request.ContentType = _content_type;
                        request.Timeout = _timeout;
                        Stream stream = request.GetRequestStream();
                        if (stream == null)
                        {
                            request.Abort();
                            request = null;
                            return;
                        }
                        stream.Write(_request_data, 0, _request_data.Length);
                        stream.Close();
                    }
                    break;
                case ContentType.JSON:
                    {
                        request = WebRequest.CreateHttp(_url);
                        request.Method = _method;
                        request.ContentType = _content_type;
                        request.Timeout = _timeout;
                        //添加token
                        //if (Main.Data.token != null)
                        //{
                        //    Debug.Log("添加token=" + Main.Data.token);
                        //    request.Headers.Add("Authorization", Main.Data.token);
                        //}
                        Stream stream = request.GetRequestStream();
                        if (stream == null)
                        {
                            request.Abort();
                            request = null;
                            return;
                        }
                        stream.Write(_request_data, 0, _request_data.Length);
                        stream.Close();
                    }
                    break;
            }

            request.ServicePoint.Expect100Continue = false;
            //request.Timeout = System.Threading.Timeout.Infinite;

            if (_url.StartsWith("https"))
                request.ProtocolVersion = HttpVersion.Version11;
            if (_cookie != null)
                request.CookieContainer = _cookie;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                if (response.ContentLength > 0)
                {
                    Stream stream = response.GetResponseStream();
                    _response_data = new byte[response.ContentLength];
                    int point = 0;
                    while (point < response.ContentLength)
                    {
                        point += stream.Read(_response_data, point, (int)response.ContentLength - point);
                    }
                    stream.Close();
                }
                else
                {
                    Stream stream = response.GetResponseStream();
                    MemoryStream memory = new MemoryStream(20480);
                    byte[] buffer = new byte[5120];
                    int point = 0;
                    while (true)
                    {
                        int count = stream.Read(buffer, 0, buffer.Length);
                        if (count == 0)
                            break;
                        point += count;
                        memory.Write(buffer, 0, count);
                    }
                    memory.Seek(0, SeekOrigin.Begin);
                    _response_data = new byte[point];
                    memory.Read(_response_data, 0, point);
                    memory.Close();
                    stream.Close();
                }
                completeEvent?.Invoke();
            }
            else
            {
                Debug.LogError(response.StatusCode.ToString());
            }
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.ToString());
        }
    }

    public byte[] GetData()
    {
        return _response_data;
    }

    public string GetText()
    {
        if (_response_data == null || _response_data.Length == 0)
            return "";
        return Encoding.UTF8.GetString(_response_data);
    }

    public void Callback()
    {
        dataHandler?.Invoke(this);
    }
}

public class HttpMethod
{
    public const string GET = "GET";
    public const string POST = "POST";
}

public class ContentType
{
    public const string FORM = "multipart/form-data;";
    public const string TEXT = "text/html;charset=UTF-8;";
    public const string JSON = "application/json;charset=UTF-8;";
}
